package hw.ats.news.util;

import hw.ats.common.ds.AdParser;
import hw.ats.common.ds.AtsParser;
import hw.ats.common.ds.ConfigParser;
import hw.ats.common.ds.RespParser;
import hw.ats.common.model.Ad;
import hw.ats.common.model.Ats;
import hw.ats.common.model.Config;
import hw.ats.common.util.DBHelper;
import hw.ats.news.ds.CmtParser;
import hw.ats.news.ds.MultiDepthCateParser;
import hw.ats.news.ds.NewsParser;
import hw.ats.news.model.Cate;
import hw.ats.news.model.Cmt;
import hw.ats.news.model.News;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.tattermedia.allthataudio.misc.DebugFlag;

public class DataLoader {
	private static final String TAG = "DataLoader";
	private static boolean ContentsUpdate = false;
	
	public static String 	OldVersion;
	/**
	 * 데이터베이스 초기화
	 * 
	 * @param activity
	 */
	public static String getContentsUpdate(){
		if (ContentsUpdate)
		return "update exist!!";
	  return "no update";
	}
	
	public static boolean checkFirst(Activity activity){
		String dbPath = "/data/data/"+activity.getApplicationContext().getPackageName()+"/databases";
		String outFilename = dbPath + "/" + App.DATABASE_NAME;
		return new File(outFilename).exists();
	}
	 
	public static void initDatabase(Activity activity) {
		String dbPath = "/data/data/"+activity.getApplicationContext().getPackageName()+"/databases";
		String outFilename = dbPath + "/" + App.DATABASE_NAME;
		if (DebugFlag.isLogEnabled())
			Log.d(TAG, "dbpath=" + outFilename);

		// 데이터베이스 초기화시...잠시 열어두고 사용함
//		new File(outFilename).delete();
//		new File(dbPath).delete();


		if (new File(outFilename).exists() == false) {
			new File(dbPath).mkdirs();

			InputStream in = null;
			OutputStream out = null;
			try {
				in = activity.getAssets().open(App.DATABASE_NAME);
				out = new FileOutputStream(outFilename);

				byte[] buf = new byte[1024];
				int len;
				while ((len = in.read(buf)) > 0) {
					out.write(buf, 0, len);
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					out.close();
				} catch (Exception ignored) {
				}
				try {
					in.close();
				} catch (Exception ignored) {
				}
			}
		}
	}
	
	/**
	 * 데이터 공급 서버로부터 API를 이용해서 최근 7일간 글을 수신하고,
	 * 데이터베이스에 등록한다.
	 */
	public static void loadRecentNews(DBHelper dbHelper) {
		NewsParser parser = new NewsParser();
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		db.beginTransaction();
		int max = News.maximumId(dbHelper.getReadableDatabase());

		try{
			for (int page = 1; page < 2; page++) { //change to 1 page
				List<News> list = parser.parse(App.NEWS_XML_URL+page);
				if (list == null || list.size() == 0)
					break;
				if (DebugFlag.isLogEnabled()) 
					Log.d(TAG, "page="+page+" / list="+list);
				
				
				for (News entry : list) {
					if (entry.uid > max) {
						
//						loadNewsBody(dbHelper, entry, false);
						
						entry.insert(db);
						
					} else {
						page = Integer.MAX_VALUE;
						break;
					}
				}
				
//				for (int i = 0, len = list.size(); i < len; i++) {
//					News news = list.get(i);
//					if (news.uid > max) {
//						
//						// load news contents
//						loadNewsBody(dbHelper, news);
//						
//						news.insert(db);
//												
//					}else {
//						page = Integer.MAX_VALUE; // 최근부터 훑어 내려오기 때문에 이미 있는 글이 하나라도 발견되면 루프를 벗어나야함
//						break;
//					}
//				}
			}
			db.setTransactionSuccessful();
		}finally
		{
			db.endTransaction();
		}
		
	}
	
	/**
	 * 데이터 공급 서버로부터 API를 이용해서 최근 7일간 글을 수신하고,
	 * 데이터베이스에 등록한다.
	 */
	public static void loadRecentNews_legacy(DBHelper dbHelper) {
		// 최근 뉴스 id 번호
		int max = News.maximumId(dbHelper.getReadableDatabase());
		
		//		if (ContentsUpdate){
		NewsParser parser = new NewsParser();
		for (int page = 1; page < 50; page++) {
			List<News> list = parser.parse(App.NEWS_XML_URL+page);
			if (list == null || list.size() == 0)
				break;

			if (DebugFlag.isLogEnabled()) 
				Log.d(TAG, "page="+page+" / list="+list);

			for (int i = 0, len = list.size(); i < len; i++) {
				News news = list.get(i);
				if (news.uid > max) {
					news.insert(dbHelper.getWritableDatabase());
				} else {
					page = Integer.MAX_VALUE; // 최근부터 훑어 내려오기 때문에 이미 있는 글이 하나라도 발견되면 루프를 벗어나야함
					break;
				}
			}
			//			}
		}
	}

	/**
	 * 추천글
	 * @param dbHelper
	 */
	public static void loadRecmdNews(DBHelper dbHelper) {
		//		if (ContentsUpdate){
		NewsParser parser = new NewsParser();
		List<News> list = parser.parse(App.NEWS_RECMD_XML_URL);
		if (list == null || list.size() == 0)
			return;

		for (int i = 0, len = list.size(); i < len; i++) {
			News news = list.get(i);
			if (News.exists(dbHelper.getReadableDatabase(), news.uid)) {
				News.markRecmd(dbHelper.getWritableDatabase(), news.uid, true);
			} else {
				news.recmd_flag = true;
				news.insert(dbHelper.getWritableDatabase());
			}
			//			}
		}
	}

	/**
	 * 글 본문
	 * @param dbHelper
	 */
	public static boolean loadNewsBody(DBHelper dbHelper, News news, boolean updateDatabase) {
		if (DebugFlag.isLogEnabled())
			Log.d(TAG, "loadNewsBody()");
		
		if (news == null)
			return false;
		
	//	if (true){
		if (news.body_html.equals("")){
			String url = App.NEWS_BODY_XML_URL+news.uid;
			if (DebugFlag.isLogEnabled())
				Log.d(TAG, "url="+url);

			NewsParser parser = new NewsParser();
			List<News> list = parser.parse(url);
			if (list == null || list.size() == 0)
				return false;

			News newsBody = list.get(0);

			news.cmt_cnt = newsBody.cmt_cnt;
			news.body_html = newsBody.body_html;
			news.url = newsBody.url;
			news.mp3_url = newsBody.mp3_url;
			news.mp3_fileSize = newsBody.mp3_fileSize;
			news.mp3_totalDuration = newsBody.mp3_totalDuration;
			
			if (updateDatabase) {
				news.updateBody(dbHelper.getWritableDatabase());
			}
			
			// 		   	displayData();
		}else{

			int cmt_cnt = DataLoader.getCmtCount(news.uid);
			if (cmt_cnt != news.cmt_cnt){
				news.cmt_cnt = cmt_cnt;
				//news.updateBody(dbHelper.getWritableDatabase());
			}

		}

		return true;
	}

	
	

	/**
	 * 분류별 최신글
	 * @param dbHelper
	 */
	public static void loadCateNews(DBHelper dbHelper, int cate_uid) {
		// 최근 뉴스 id 번호
		SQLiteDatabase db = dbHelper.getWritableDatabase();	
		int max = News.maximumId(dbHelper.getReadableDatabase(), cate_uid);
		db.beginTransaction();
		NewsParser parser = new NewsParser();
		try{

			for (int page = 1; page < 5; page++) {
				List<News> list = parser.parse(App.NEWS_CATE_XML_URL + cate_uid+"&page="+page);
				if (list == null || list.size() == 0)
					break;
				if (DebugFlag.isLogEnabled()) 
					Log.d(TAG, "page="+page+" / list="+list);
				for (int i = 0, len = list.size(); i < len; i++) {
					News news = list.get(i);
					if (news.uid > max) {
						
						
						
						news.insert(db);
					}else {
						page = Integer.MAX_VALUE; // 최근부터 훑어 내려오기 때문에 이미 있는 글이 하나라도 발견되면 루프를 벗어나야함
						break;
					}
				}
			}
			db.setTransactionSuccessful();
		}finally{
			db.endTransaction();
		}
	}

	

	
	/**
	 * 분류별 최신글
	 * @param dbHelper
	 */
	public static void loadCateNews_legacy(DBHelper dbHelper, int cate_uid) {
		// 최근 뉴스 id 번호
		int max = News.maximumId(dbHelper.getReadableDatabase(), cate_uid);
		
		NewsParser parser = new NewsParser();
		for (int page = 1; page < 50; page++) {
			List<News> list = parser.parse(App.NEWS_CATE_XML_URL + cate_uid+"&page="+page);
			if (list == null || list.size() == 0)
				break;
			
			if (DebugFlag.isLogEnabled()) 
				Log.d(TAG, "page="+page+" / list="+list);
			
			for (int i = 0, len = list.size(); i < len; i++) {
				News news = list.get(i);
				if (news.uid > max)
					news.insert(dbHelper.getWritableDatabase());
			}
		}
	}
	
	/**
	 * 데이터 공급 서버로부터 API를 이용해서 시리즈 전체 목록을 수신하고,
	 * 데이터베이스를 업데이트 한다.
	 */
	public static void loadAtsList(DBHelper dbHelper) {
		AtsParser parser = new AtsParser();
		List<Ats> list = parser.parse(App.ATS_XML_URL);
		for (int i = 0, len = list.size(); i < len; i++) {
			Ats ats = list.get(i);
			if (ats.exist(dbHelper.getReadableDatabase()))
				ats.update(dbHelper.getWritableDatabase());
			else
				ats.insert(dbHelper.getWritableDatabase());
			if (DebugFlag.isLogEnabled()) 
				Log.d(TAG, "ats.title="+ats.title);
		}
	}
	
	public static boolean loadConfig(DBHelper dbHelper) {
		if (DebugFlag.isLogEnabled()) 
			Log.d(TAG, "cfg="+App.CONFIG_XML_URL);
		boolean ContentsUpdate = false;
		ConfigParser p = new ConfigParser(App.CONFIG_XML_URL);
		Config config = p.parse();
		Log.d("CONFIG VERSION", config.version);
		Config oldConfig = null;
		String[] arr_oldContentsVersion ;
		String[] arr_currentContentsVersion ;
		String oldContentsVersion = "0";
		String currentContentsVersion = "1";
		if (config == null)
			return false;//TODO:

		if (config.exist(dbHelper.getReadableDatabase())){
			oldConfig = Config.load(dbHelper.getReadableDatabase());
			Log.d("OLD CONFIG VERSION", oldConfig.version);
			//	String[] arr_version ;
			//TODO : make sure about the version information have 3 part. and make sure everything OK even though version information 
			// is not qualified

			arr_oldContentsVersion = oldConfig.version.split("\\.");
			
			Log.d("split length", String.valueOf(arr_oldContentsVersion.length));
			if (arr_oldContentsVersion.length > 2)
				oldContentsVersion = arr_oldContentsVersion[2];

			Log.d("OLD VERSION", oldContentsVersion);


			arr_currentContentsVersion  = config.version.split("\\.");
			
			if (arr_currentContentsVersion.length >2 )
				currentContentsVersion = arr_currentContentsVersion[2];
			Log.d("CURRNT VERSION", currentContentsVersion);

			if (!oldContentsVersion.equals(currentContentsVersion)){
				config.update(dbHelper.getWritableDatabase());
				ContentsUpdate = true;
				Log.d("UPDATE VERIFY...", String.valueOf(ContentsUpdate));
				Log.d("CURRNT VERSION", currentContentsVersion);
				Log.d("OLD VERSION", oldContentsVersion);

			}else{
				ContentsUpdate = false;
				Log.d("UPDATE VERIFY...", String.valueOf(ContentsUpdate));
			}
		}else{			
			config.insert(dbHelper.getWritableDatabase());
			ContentsUpdate = true;
		}
		
		OldVersion = oldContentsVersion;
		
		if (DebugFlag.isLogEnabled()) 
			Log.d(TAG, "config.title="+config.title);
		
		return ContentsUpdate;
	}
	
	public static void loadAd(DBHelper dbHelper) {
		if (DebugFlag.isLogEnabled()) 
			Log.d(TAG, "ad="+App.AD_XML_URL);
		
		AdParser p = new AdParser(App.AD_XML_URL);
		List<Ad> ads = p.parse();
		if (ads == null || ads.size() == 0)
			return;//TODO:

		Ad ad = ads.get(0);
		if (ad.exist(dbHelper.getReadableDatabase()))
			ad.update(dbHelper.getWritableDatabase());
		else
			ad.insert(dbHelper.getWritableDatabase());
		
		if (DebugFlag.isLogEnabled()) 
			Log.d(TAG, "ad="+ad.image);
	}
	
	/**
	 * 데이터 공급 서버로부터 API를 이용해서 카테고리 정보를 조회하고,
	 * 데이터베이스에 등록한다.
	 */
	public static void loadCategory(DBHelper dbHelper) { //TODO:업데이트되도록해야함
		if (DebugFlag.isLogEnabled()) 
			Log.d(TAG, "cate-url="+App.CATEGORY_XML_URL);
			MultiDepthCateParser parser = new MultiDepthCateParser(App.CATEGORY_XML_URL);
			List<Cate> list = parser.parse();
			for (int i = 0, len = list.size(); i < len; i++) {
				Cate cate = list.get(i);
				if (DebugFlag.isLogEnabled()) 
					Log.d(TAG, "pre cate="+cate);
				
				Cate existed = Cate.load(dbHelper.getReadableDatabase(), cate.uid);
				
				if (existed != null) {
					cate.update(dbHelper.getWritableDatabase());
				} else {
					cate.insert(dbHelper.getWritableDatabase());
				}
				
				if (DebugFlag.isLogEnabled()) 
					Log.d(TAG, "post cate="+cate);	
		}
	}
	
	/**
	 * 댓글 로드
	 * @param art_uid
	 * @param start
	 * @param rows
	 * @return
	 */
	public static List<Cmt> loadCmtList(int art_uid, int start, int rows) {
		//String url = App.CMT_XML_URL+art_uid;
		String url = App.CMT_XML_URL+art_uid+"?expire=1";
		if (DebugFlag.isLogEnabled())
			Log.d(TAG, "url="+url);
		CmtParser parser = new CmtParser(url);
		List<Cmt> list = parser.parse();
		return list;
	}

	/**
	 * 설치된 All That 목록 반환
	 * @param sender
	 * @return
	 */
	public static List<String> findAllThatSeries(Activity sender) {
		List<String> res = new ArrayList<String>();
	    final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
	    mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
	    final List<ResolveInfo> pkgAppsList = sender.getPackageManager().queryIntentActivities(mainIntent, 0);
	    for (int i = 0, len = pkgAppsList.size(); i < len; i++) {
	    	String pkgName = pkgAppsList.get(i).activityInfo.packageName;
	    	if (pkgName.startsWith(App.ALL_THATS_SERIES_PKG_PREFIX))
	    		res.add(pkgName);
	    }
	    return res;
	}

	/**
	 * News 수신
	 * @param url
	 * @return
	 */
	public static List<News> fetchNews(String url) {
		NewsParser parser = new NewsParser();
		List<News> items = parser.parse(url);
		return items;
	}
	
	/**
	 * 댓글 등록
	 * @param cmt
	 * @return -1 : 인코딩 에러, -2 : 전송 에러, -3 : 서버측 컨텐츠 제공시 오류
	 */
	public static int postCmt(Cmt cmt) {
		String url = App.CMT_ADD_XML_URL;
		
		StringBuilder p = new StringBuilder();
		try {
			p.append("entryid=").append(cmt.news_uid).append("&");
			p.append("name=").append(URLEncoder.encode(cmt.author, "UTF-8")).append("&");
			p.append("homepage=").append(URLEncoder.encode(cmt.homepage, "UTF-8")).append("&");
			p.append("password=").append(URLEncoder.encode(cmt.passwd, "UTF-8")).append("&");
			if (cmt.pid > 0) 
				p.append("parentid=").append(cmt.pid).append("&");
			p.append("content=").append(URLEncoder.encode(cmt.body, "UTF-8"));
		} catch (Exception e) {
			return -1;
		}
		
		if (DebugFlag.isLogEnabled())
			Log.d(TAG, "postCmt="+p);
		
		String res = requestHttpPost(url, p.toString());
		if (res == null) {
			return -2;
		}
		
		RespParser parser = new RespParser();
		
		try {
			parser.parse(res);
		} catch (Exception e) {
			e.printStackTrace();
			return -3;
		}
		
		if (parser.errorCode == 0)
			return 0;
		
		return -3;
	}
	
	/**
	 * 댓글 변경
	 * @param cmt
	 * @return -1 : 인코딩 에러, -2 : 전송 에러, -3 : 서버측 컨텐츠 제공시 오류
	 */
	public static int updateCmt(Cmt cmt) {
		String url = App.CMT_MOD_XML_URL+cmt.uid;
		
		StringBuilder p = new StringBuilder();
		try {
			p.append("name=").append(URLEncoder.encode(cmt.author, "UTF-8")).append("&");
			p.append("homepage=").append(URLEncoder.encode(cmt.homepage, "UTF-8")).append("&");
			p.append("password=").append(URLEncoder.encode(cmt.passwd, "UTF-8")).append("&");
			p.append("content=").append(URLEncoder.encode(cmt.body, "UTF-8"));
		} catch (Exception e) {
			return -1;
		}
		
		if (DebugFlag.isLogEnabled())
			Log.d(TAG, "updateCmt="+p);
		
		String res = requestHttpPost(url, p.toString());
		if (res == null) {
			return -2;
		}
		
		RespParser parser = new RespParser();
		
		try {
			parser.parse(res);
		} catch (Exception e) {
			e.printStackTrace();
			return -3;
		}
		
		if (parser.errorCode == 0)
			return 0;
		
		return -3;
	}
	
	/**
	 * 댓글 삭제
	 * @param cmt
	 * @return
	 */
	public static int deleteCmt(Cmt cmt) {
		String url = App.CMT_DEL_XML_URL + cmt.uid;

		StringBuilder p = new StringBuilder();
		try {
			p.append("password=").append(URLEncoder.encode(cmt.passwd, "UTF-8"));
		} catch (Exception e) {
			return -1;
		}

		if (DebugFlag.isLogEnabled())
			Log.d(TAG, "deleteCmt="+p);
		
		String res = requestHttpPost(url, p.toString());
		if (res == null) {
			return -2;
		}

		RespParser parser = new RespParser();

		try {
			parser.parse(res);
		} catch (Exception e) {
			e.printStackTrace();
			return -3;
		}

		if (parser.errorCode == 0)
			return 0;

		return -3;
	}
	/**
	 * 댓글 갯수 가져오기 
	 * 
	 */
	public static int getCmtCount(int entryid){
		String cmt_cnt_url = App.CMT_CNT_XML_URL + String.valueOf(entryid);
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();		
		try{
			DocumentBuilder builder = dbFactory.newDocumentBuilder();
			System.out.println(cmt_cnt_url);

//			System.out.println(new URL(cmt_cnt_url).toString());
			URL url= new URL(cmt_cnt_url);
			//HttpURLConnection con = (HttpURLConnection)url.openConnection();
	       // InputStream in  = con.getInputStream();
			InputStream in = url.openStream();
	        Document dom = builder.parse(in);
	        NodeList items = dom.getElementsByTagName("comment_count");
	        if (items.getLength() > 0 )
		        	return Integer.parseInt(items.item(0).getFirstChild().getNodeValue());
		}catch (Exception e ){
			//throw new RuntimeException(e);
			e.printStackTrace();
		}
		return -1;
	}
	

	/**
	 * POST 전송
	 * 
	 * @param urlstring
	 * @param params
	 * @return
	 */
	private static String requestHttpPost(String urlstring, String params) {
		try {
			URL url = new URL(urlstring);
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			con.setDoInput(true);
			con.setRequestProperty("Content-Type",
					"application/x-www-form-urlencoded");
			con.setRequestMethod("POST");
			con.setDoOutput(true);

			OutputStream out_stream = con.getOutputStream();
			out_stream.write(params.getBytes("UTF-8"));
			out_stream.flush();
			out_stream.close();

			InputStream is = null;
			BufferedReader in = null;
			String data = "";

			is = con.getInputStream();
			in = new BufferedReader(new InputStreamReader(is), 8 * 1024);

			String line = null;
			StringBuffer buff = new StringBuffer();

			while ((line = in.readLine()) != null) {
				buff.append(line + "\n");
			}
			data = buff.toString().trim();
			
			return data;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}
